#ifndef MINI_BASIC_PARSER_SUPPORT_H
#define MINI_BASIC_PARSER_SUPPORT_H

#pragma once

#include "stdafx.h"
#include "../Parser/Vals.h"
#include "Visitors.h"
#include <memory>
#include <wtypes.h>

typedef struct _ExecutionParameters ExecutionParameters;

namespace MiniBasic
{
    class Environment;

    // returned by the parser when the rest of the current line
    // should be skipped and execution continued elsewhere
    // the lexer's position should be adjusted before returning
    static const int CONTINUE_EXECUTION = 2;
    static const int FOR_EXITED = 3;

    template<class T>
    bool GetExprValue(const var_type& v1, T& vt)
    {
        using namespace MiniBasic;
        apply_result<T> res = boost::apply_visitor(get_underlying_value<T>(), v1);
        if(res)
        {
            vt = res.result;
        }
        return res;
    }

    template<class T>
    bool GetExprValue(const Vals& v1, T& vt)
    {
        return GetExprValue(v1.var, vt);
    }

    template<class Elem, class Alloc, class OutputIterator>
    void ExplodeDelimitedString(const std::basic_string<Elem, std::char_traits<Elem>, Alloc>& inString, Elem delimiter, OutputIterator it)
    {
        typedef std::basic_string<Elem, std::char_traits<Elem>, Alloc> string_type;
        string_type::size_type pos = 0, previous = 0;
        while((pos = inString.find(delimiter, pos)) != string_type::npos)
        {
            (*it)++ = string_type(inString, previous, pos - previous);
            // increment size so we don't immediately re-find the same element
            previous = ++pos;
        }
        // put the rest on after the last delimiter
        (*it)++ = string_type(inString, previous, string_type::npos);
    }

    std::string StringifyExpression(const var_type& v1, mbint numberPadding = 0);
    std::string StringifyExpression(const Vals& v1, mbint numberPadding = 0);

    HRESULT CreateExecutionEnvironment(ExecutionParameters* pExParams, std::auto_ptr<Environment>& env);
    HMODULE GetDllModuleHandle();
}

#endif
